package com.franklin.ideaplugin.maphelper.resolver.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.franklin.ideaplugin.api.beans.declaration.IDeclaration;
import com.franklin.ideaplugin.api.utils.psi.PsiMethodUtils;
import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.col.declaration.IColDeclaration;
import com.franklin.ideaplugin.maphelper.resolver.IColMemberResolver;
import com.franklin.ideaplugin.maphelper.utils.PsiColUtils;
import com.google.common.collect.Sets;
import com.intellij.psi.*;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * 方法返回表达
 *
 * @author Ye Junhui
 * @since 2024/3/5
 */
public abstract class AbstractMethodCallExpressionColMemberResolver implements IColMemberResolver {

    @Override
    public boolean supports(IColDeclaration colDeclaration) {
        IDeclaration declaration = colDeclaration.getDeclaration();
        Boolean result = Optional.ofNullable(declaration.getCreateExpression(PsiMethodCallExpression.class))
                .map(PsiMethodCallExpression::resolveMethod)
                .map(PsiMethod::getReturnType)
                .filter(PsiClassType.class::isInstance)
                .map(psiType -> (PsiClassType) psiType)
                .map(PsiClassType::resolve)
                .map(this::isTargetClass)
                .orElse(false);

        return result;
    }

    @Override
    public Collection<IColMember> resolveColMembers(PsiElement psiExpression, IColDeclaration colDeclaration) {
        //结果
        Set<IColMember> result = Sets.newLinkedHashSet();
        //本地变量
        IDeclaration declaration = colDeclaration.getDeclaration();

        //当前代码块
        Collection<IColMember> currentMembers = getNewExpressionColMemberResolver().resolveColMembers(psiExpression, colDeclaration);
        CollectionUtil.addAll(result,currentMembers);

        //方法调用
        PsiMethodCallExpression psiMethodCallExpression = declaration.getCreateExpression(PsiMethodCallExpression.class);

        //方法
        PsiMethod psiMethod = psiMethodCallExpression.resolveMethod();

        //方法的返回表达式
        List<PsiExpression> returnExpressionList = PsiMethodUtils.findMethodReturnExpression(psiMethod);
        if (CollectionUtil.isEmpty(returnExpressionList)){
            return result;
        }
        returnExpressionList.forEach(returnExpression -> {
            IColDeclaration methodMapDeclaration = PsiColUtils.findColExpressionDeclaration(returnExpression);

            //解析成员
            Collection<IColMember> psiColMembers = getColMemberResolverFactory()
                    .resolveExpression(returnExpression, methodMapDeclaration);
            CollectionUtil.addAll(result, psiColMembers);
        });

        return result;
    }

    /**
     * 是否是目标类
     * @param psiClass
     * @return
     */
    protected abstract boolean isTargetClass(PsiClass psiClass);

    /**
     * new表达式解析器
     * @return
     */
    protected abstract AbstractNewExpressionColMemberResolver getNewExpressionColMemberResolver();

}
